// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//


#pragma once

#include <melon/random.h>

#include <boost/random/uniform_01.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <boost/random/uniform_real_distribution.hpp>

#include <pollux/expression/complex_writer_types.h>

namespace kumo::pollux {
    namespace generator_spec_utils {
        vector_size_t getRandomIndex(FuzzerGenerator &rng, vector_size_t maxIndex);

        BufferPtr generateNullsBuffer(
            FuzzerGenerator &rng,
            memory::MemoryPool *pool,
            vector_size_t vectorSize,
            double nullProbability);

        BufferPtr generateIndicesBuffer(
            FuzzerGenerator &rng,
            memory::MemoryPool *pool,
            vector_size_t bufferSize,
            vector_size_t baseVectorSize);
    } // namespace generator_spec_utils

    namespace fuzzer {
        /// Used to write variants to a GenericWriter, recursively calls itself for
        /// complex types.
        template<TypeKind KIND>
        void writeOne(const variant &v, exec::GenericWriter &writer) {
            using T = typename TypeTraits<KIND>::NativeType;
            writer.template castTo<T>() = v.value<KIND>();
        }

        template<>
        void writeOne<TypeKind::VARCHAR>(const variant &v, exec::GenericWriter &writer);

        template<>
        void writeOne<TypeKind::VARBINARY>(
            const variant &v,
            exec::GenericWriter &writer);

        template<>
        void writeOne<TypeKind::ARRAY>(const variant &v, exec::GenericWriter &writer);

        template<>
        void writeOne<TypeKind::MAP>(const variant &v, exec::GenericWriter &writer);

        template<>
        void writeOne<TypeKind::ROW>(const variant &v, exec::GenericWriter &writer);
    } // namespace fuzzer
} // namespace kumo::pollux
